#include "Fifo.h"
#include "Logger.h"
#include <errno.h>

Fifo::Fifo(std::string nombre,bool lectura ) {
	this->nombre = nombre;
	this->fileDes = -1;

	if(lectura){
		crear();
		openForRead();
	}
}


void Fifo::openForRead(){
	isLectura = true;
	Logger::instancia() << "Fifo::openForRead - inicio .de :" << nombre << eol;
	// se abre el file descriptor para lectura
	if (this->fileDes == -1){
		Logger::instancia() << "Fifo::openForRead - hago open lectura de :" << nombre << eol;
		this->fileDes = open(this->nombre.c_str(), O_RDONLY);
		Logger::instancia() << "Fifo::openForRead - open fin de:" << nombre <<eol;
		if(this->fileDes == -1){
			Logger::instancia() << "Fifo::openForRead - ERROR - FIFO no pudo hacer open del fifo:" << nombre << eol;
			exit(-1);
		}

	}
}

void Fifo::openForWrite(){
	isLectura = false;
	// se abre el file descriptor para escritura
	if (this->fileDes == -1){
		Logger::instancia() << "Fifo::openForWrite - hago open escritura de :" << nombre << eol;
		this->fileDes = open(this->nombre.c_str(), O_WRONLY);
		Logger::instancia() << "Fifo::openForWrite - open fin de:" << nombre <<eol;
		if(this->fileDes == -1){
			Logger::instancia() << "Fifo::openForWrite - ERROR - FIFO no pudo hacer open del fifo:" << nombre << eol;
			exit(-1);
		}

	}
}

Fifo::~Fifo() {
	Logger::instancia() << "Fifo::~Fifo - Salgo del fifo. " << nombre << " -Es lectura?:" << this->isLectura << eol;
}


int Fifo::crear(){
	// se crea el fifo
	int error = mknod(nombre.c_str(), S_IFIFO | 0770, 0);
	Logger::instancia() << "Fifo::Fifo - Abro el fifo. " << nombre <<eol;

	return error;
}

int Fifo::escribir(const char *dato, int datoSize) {
	Logger::instancia() << "Fifo::escribir - tamano mensaje:" << datoSize << eol;

	openForWrite();

	// se escriben los datos en el fifo
	int resultado = write(this->fileDes, (const void*) dato, datoSize);
	Logger::instancia() << "Fifo::escribir - Escribo mensaje size:" << datoSize << " en:" << nombre << eol;

	if(resultado < datoSize){
		Logger::instancia() << "Fifo::escribir - ERROR - FIFO no pudo escribir, el tamano esperado del fifo:" << nombre << " esperaba:" << datoSize << " escribi:"<<resultado << eol;
		exit(-1);
	}

	if(resultado == -1){
		Logger::instancia() << "Fifo::escribir - ERROR - FIFO no pudo escribir el fifo:" << nombre << eol;
		exit(-1);
	}

	return resultado;
}

int Fifo::leer(char *buffer, int buffSize) {
	openForRead();

	// se leen los datos del fifo
	int resultado = 0;
	resultado = read(this->fileDes, (void*) buffer, buffSize);

	if(resultado < buffSize){
		Logger::instancia() << "Fifo::leer - ERROR - FIFO no pudo leer, el tamano esperado del fifo:" << nombre << " esperaba:" << buffSize << " obtuve:"<<resultado << eol;
	}

	return resultado;
}

std::string Fifo::getNombre(){
	return this->nombre;
}

void Fifo::cerrar() {
	Logger::instancia() << "Fifo::cerrar - Cierro fifo:" << nombre << " -Es lectura?:" << this->isLectura << eol;
	if (this->fileDes != -1)
		close(this->fileDes);

	this->fileDes = -1;
}


void Fifo::eliminar() const {
	Logger::instancia() << "Fifo::eliminar - elimino fifo:" << nombre << " -Es lectura?:" << this->isLectura << eol;
	unlink ( nombre.c_str() );
}

